package com.ciaojian.core.filter;

import com.auth0.jwt.interfaces.Claim;
import com.ciaojian.core.util.JwtUtil;
import com.ciaojian.core.util.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * JWT过滤器，拦截 /secure的请求
 *
 * @author Atlakyn
 */
@WebFilter(filterName = "JwtFilter", urlPatterns = {"/client/*"})
public class JwtFilter implements Filter {
    /**
     * 不需要过滤的 URL
     */
    private static final Set<String> ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(
            Collections.singletonList("/login/test")));

    @Override
    public void init(FilterConfig filterConfig)  {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;

        // 判断请求路径是不是在排除列表内
        if (exclude(request)) {
            chain.doFilter(servletRequest, servletResponse);
            return;
        }

        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        // 获取 header里的token
        final String token = request.getHeader("authorization");
        // 不拦截 options 请求
        if (RequestMethod.OPTIONS.name().equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            chain.doFilter(request, response);
        }
        // Except OPTIONS, other request should be checked by JWT
        else if (token == null) {
            Assert.notNull(token,"登录过期,请重新登录");
            PrintWriter writer = response.getWriter();
            writer.print(new ObjectMapper().writeValueAsString(Result.error("登录过期,请重新登录")));
            return;
        }

        Map<String, Claim> userData = JwtUtil.verifyToken(token);
        if (userData == null) {
            response.getWriter().write(new ObjectMapper().writeValueAsString(Result.error("Token 不合法")));
            return;
        }
        Integer id = userData.get("id").asInt();
        String name = userData.get("name").asString();
        String userName = userData.get("userName").asString();
        //拦截器 拿到用户信息，放到request中
        request.setAttribute("id", id);
        request.setAttribute("name", name);
        request.setAttribute("userName", userName);
        chain.doFilter(servletRequest, servletResponse);
    }


    @Override
    public void destroy() {

    }

    /**
     * 判断请求路径是不是在排除列表内
     *
     * @param request http request
     * @return 包含返回 true
     */
    private boolean exclude(HttpServletRequest request) {
        // 请求路径
        String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", "");
        return ALLOWED_PATHS.contains(path);
    }
}
